from random import randint

from django.conf import settings
from django.contrib.auth.hashers import check_password, make_password
from django.core.cache import cache

from common.errors import InvalidAction, InvalidParameter
from user_center import tasks
from user_center.models import CampusIdentity, User


class UserService:
    def __init__(
        self, user_repository, campus_identity_repository, user_log_repository
    ):
        self.user_repository = user_repository
        self.campus_identity_repository = campus_identity_repository
        self.user_log_repository = user_log_repository

    def register(self, username: str, password: str, email: str, code: str):
        if not email:
            raise InvalidParameter("无效邮箱！")
        email_verification_code = cache.get(
            "email_verification_code_4_register_" + email
        )
        if code != email_verification_code:
            raise InvalidParameter("邮箱验证码错误！")
        total, users = self.user_repository.get_users(username=username)
        if total > 0:
            raise InvalidParameter("用户名重复！")
        self.user_repository.save_or_update(
            User(
                username=username,
                password=make_password(
                    password, salt=settings.USER_CENTER_PASSWORD_SECRET_KEY
                ),
                email=email,
            )
        )

    def update_user_info_by_id(self, **kwargs):
        User.objects.filter(id=kwargs.get("id")).update(**kwargs)

    def send_email_verification_code_4_register(self, email: str) -> int:
        """返回异步任务id"""
        total, users = self.user_repository.get_users(email=email)
        if total > 0:
            raise InvalidParameter("此邮箱已被别的用户使用！")
        verification_code = cache.get("email_verification_code_4_register_" + email)
        if verification_code:
            raise InvalidAction("120秒内请勿重复获取验证码！")
        verification_code = randint(1000, 9999)
        cache.set(
            "email_verification_code_4_register_" + email,
            str(verification_code),
            timeout=120,
        )
        task = tasks.send_email_task.s(
            "欢迎注册青动", "您的验证码是{}，请在120秒内使用！".format(verification_code), [email]
        ).apply_async()
        return task.id

    def send_email_verification_code_4_login(self, email: str) -> int:
        """返回异步任务id"""
        total, users = self.user_repository.get_users(email=email)
        if total <= 0:
            raise InvalidAction("用户未注册！")
        verification_code = cache.get("email_verification_code_4_login_" + email)
        if verification_code:
            raise InvalidAction("120秒内请勿重复获取验证码！")
        verification_code = randint(1000, 9999)
        cache.set(
            "email_verification_code_4_login_" + email,
            str(verification_code),
            timeout=120,
        )
        task = tasks.send_email_task.s(
            "欢迎登录青动", "您的验证码是{}，请在120秒内使用！".format(verification_code), [email]
        ).apply_async()
        return task.id

    def login(self, email: str, password: str, email_verification_code: str) -> str:
        """使用密码或用邮箱验证码登录，成功则返回token"""
        total, users = self.user_repository.get_users(email=email)
        if total <= 0:
            raise InvalidParameter("账户不存在！")
        user = users[0]
        if password and not check_password(password, user.password):
            raise InvalidParameter("密码错误！")
        if (
            email_verification_code
            and cache.get("email_verification_code_4_login_" + email)
            == email_verification_code
        ):
            raise InvalidParameter("验证码错误！")
        return user.token

    def get_user_info(self, user_id: int) -> dict:
        total, users = self.user_repository.get_users(pk=user_id)
        if total <= 0:
            raise InvalidParameter("用户不存在")
        user = users[0]
        return {
            "username": user.username,
            "personal_profile": user.personal_profile,
            "sex": user.sex,
            "email": user.email,
            "avatar": user.avatar,
            "birthday": user.birthday.strftime("%Y-%m-%d") if user.birthday else "",
            "campus_identity": {
                "campus_name": user.campus_identity.campus_name,
                "major": user.campus_identity.major,
                "class_name": user.campus_identity.class_name,
                "admission_date": user.campus_identity.admission_date
                if user.campus_identity.admission_date
                else "",
            }
            if user.campus_identity
            else {},
        }

    def update_email_by_id(self, **kwargs):
        verification_code = cache.get(
            "email_verification_code_4_change_email_" + kwargs.get("email")
        )
        if verification_code != kwargs.get("code"):
            raise InvalidParameter("验证码错误！")
        User.objects.filter(id=kwargs.get("id")).update(email=kwargs.get("email"))

    def send_email_verification_code_4_change_email(self, email: str) -> int:
        """返回异步任务id"""
        total, users = self.user_repository.get_users(email=email)
        if total > 0:
            raise InvalidParameter("此邮箱已被别的用户使用！")
        verification_code = cache.get("email_verification_code_4_change_email_" + email)
        if verification_code:
            raise InvalidAction("120秒内请勿重复获取验证码！")
        verification_code = randint(1000, 9999)
        cache.set(
            "email_verification_code_4_change_email_" + email,
            str(verification_code),
            timeout=120,
        )
        task = tasks.send_email_task.s(
            "青动用户中心", "您的验证码是{}，请在120秒内使用！".format(verification_code), [email]
        ).apply_async()
        return task.id

    def update_campus_identity(self, **kwargs):
        user = User.objects.get(id=kwargs.get("id"))
        kwargs.pop("id")
        campus_identity = CampusIdentity.objects.create(**kwargs)
        user.campus_identity = campus_identity
        user.save()
